import logging
import os
import time
import traceback
import struct
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem, QHBoxLayout, 
                           QHeaderView, QAbstractItemView, QPushButton, QLineEdit, QFileDialog, 
                           QGroupBox, QMessageBox, QSplitter, QSizePolicy, QRadioButton, QComboBox, QApplication,
                           QDialog, QTextEdit, QScrollArea, QFrame)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIntValidator, QFont
from frame_processor import FrameProcessor
from multi_format_frame_processor import MultiFormatFrameProcessor
from progress_dialog import ProgressDialog
from file_loader_thread import FileLoaderThread
from utils import get_resource_path, format_hex_with_space
from logger import logger

class ErrorPositionDialog(QDialog):
    """误码位置详细显示对话框"""
    
    def __init__(self, parent=None, frame_index=0, error_positions=None, compare_ranges=None, 
                 reference_frame=None, current_frame=None):
        super().__init__(parent)
        self.setWindowTitle(f"帧 {frame_index} 误码位置详细信息")
        self.setModal(True)
        self.resize(800, 600)
        
        # 设置样式
        self.setStyleSheet("""
            QDialog {
                background-color: #f5f5f5;
            }
            QLabel {
                font-size: 12px;
                padding: 5px;
            }
            QTextEdit {
                font-family: 'Courier New', monospace;
                font-size: 10px;
                background-color: white;
                border: 1px solid #ccc;
                border-radius: 3px;
            }
            QPushButton {
                background-color: #0064c8;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #0055a5;
            }
            QGroupBox {
                font-weight: bold;
                border: 2px solid #ccc;
                border-radius: 5px;
                margin-top: 10px;
                padding-top: 10px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 5px;
                background-color: #f5f5f5;
            }
        """)
        
        layout = QVBoxLayout()
        
        # 基本信息
        info_group = QGroupBox("基本信息")
        info_layout = QVBoxLayout()
        
        info_text = f"帧序号: {frame_index}\n"
        if error_positions:
            info_text += f"误码位置总数: {len(error_positions)}\n"
            info_text += f"比较范围: {self._format_ranges(compare_ranges)}"
        else:
            info_text += "无误码位置"
            
        info_label = QLabel(info_text)
        info_layout.addWidget(info_label)
        info_group.setLayout(info_layout)
        layout.addWidget(info_group)
        
        if error_positions and len(error_positions) > 0:
            # 误码位置按范围分组显示
            positions_group = QGroupBox("误码位置详细信息")
            positions_layout = QVBoxLayout()
            
            # 创建滚动区域
            scroll_area = QScrollArea()
            scroll_widget = QWidget()
            scroll_layout = QVBoxLayout(scroll_widget)
            
            # 按比较范围分组显示误码位置
            if compare_ranges:
                for range_idx, (start_byte, end_byte) in enumerate(compare_ranges):
                    range_positions = [pos for pos in error_positions if start_byte <= pos <= end_byte]
                    if range_positions:
                        # 范围标题
                        range_title = QLabel(f"范围 {range_idx + 1}: 字节 {start_byte}-{end_byte} ({len(range_positions)} 个误码位置)")
                        range_title.setStyleSheet("font-weight: bold; color: #d32f2f; background-color: #ffebee; padding: 5px; border-radius: 3px;")
                        scroll_layout.addWidget(range_title)
                        
                        # 创建误码位置的详细显示
                        positions_text = self._create_detailed_positions_text(range_positions, start_byte, end_byte,
                                                                             reference_frame, current_frame)
                        
                        positions_display = QTextEdit()
                        positions_display.setPlainText(positions_text)
                        positions_display.setMaximumHeight(200)
                        positions_display.setReadOnly(True)
                        scroll_layout.addWidget(positions_display)
                        
                        # 添加分隔线
                        line = QFrame()
                        line.setFrameShape(QFrame.HLine)
                        line.setFrameShadow(QFrame.Sunken)
                        scroll_layout.addWidget(line)
            else:
                # 如果没有范围信息，直接显示所有位置
                all_positions_text = self._create_simple_positions_text(error_positions)
                positions_display = QTextEdit()
                positions_display.setPlainText(all_positions_text)
                positions_display.setReadOnly(True)
                scroll_layout.addWidget(positions_display)
            
            scroll_area.setWidget(scroll_widget)
            scroll_area.setWidgetResizable(True)
            positions_layout.addWidget(scroll_area)
            positions_group.setLayout(positions_layout)
            layout.addWidget(positions_group)
        
        # 按钮
        button_layout = QHBoxLayout()
        button_layout.addStretch()
        
        # 导出Excel按钮
        export_btn = QPushButton("导出Excel")
        export_btn.clicked.connect(self._export_to_excel)
        button_layout.addWidget(export_btn)
        
        close_btn = QPushButton("关闭")
        close_btn.clicked.connect(self.accept)
        button_layout.addWidget(close_btn)
        
        layout.addLayout(button_layout)
        self.setLayout(layout)
        
        # 保存参数以供导出使用
        self.frame_index = frame_index
        self.error_positions = error_positions
        self.compare_ranges = compare_ranges
        self.reference_frame = reference_frame
        self.current_frame = current_frame
    
    def _format_ranges(self, ranges):
        """格式化比较范围"""
        if not ranges:
            return "未知"
        range_strs = []
        for start, end in ranges:
            range_strs.append(f"{start}-{end}")
        return ", ".join(range_strs)
    
    def _create_detailed_positions_text(self, positions, start_byte, end_byte, reference_frame, current_frame):
        """创建详细的误码位置文本，包含数据对比"""
        text_lines = []
        text_lines.append(f"误码位置列表 (共 {len(positions)} 个):")
        text_lines.append("=" * 60)
        
        # 按行显示，每行显示10个位置
        for i in range(0, len(positions), 10):
            line_positions = positions[i:i+10]
            position_str = ", ".join(f"{pos:4d}" for pos in line_positions)
            text_lines.append(f"位置: {position_str}")
        
        text_lines.append("")
        text_lines.append("数据对比详情:")
        text_lines.append("=" * 60)
        text_lines.append("位置   标准值  实际值  差异(XOR)")
        text_lines.append("-" * 35)
        
        # 显示前50个误码位置的详细数据对比
        display_count = min(50, len(positions))
        for i in range(display_count):
            pos = positions[i]
            try:
                if (reference_frame and current_frame and 
                    'payload' in reference_frame and 'payload' in current_frame and
                    pos < len(reference_frame['payload']) and pos < len(current_frame['payload'])):
                    
                    ref_byte = reference_frame['payload'][pos]
                    cur_byte = current_frame['payload'][pos]
                    
                    # 确保是整数类型
                    if isinstance(ref_byte, bytes):
                        ref_byte = ref_byte[0] if len(ref_byte) > 0 else 0
                    if isinstance(cur_byte, bytes):
                        cur_byte = cur_byte[0] if len(cur_byte) > 0 else 0
                    
                    xor_result = ref_byte ^ cur_byte
                    text_lines.append(f"{pos:4d}   0x{ref_byte:02X}    0x{cur_byte:02X}    0x{xor_result:02X}")
                else:
                    text_lines.append(f"{pos:4d}   --      --      --")
            except Exception as e:
                text_lines.append(f"{pos:4d}   错误: {str(e)}")
        
        if len(positions) > display_count:
            text_lines.append(f"... 还有 {len(positions) - display_count} 个误码位置未显示")
        
        return "\n".join(text_lines)
    
    def _create_simple_positions_text(self, positions):
        """创建简单的误码位置文本"""
        text_lines = []
        text_lines.append(f"误码位置列表 (共 {len(positions)} 个):")
        text_lines.append("=" * 50)
        
        # 按行显示，每行显示15个位置
        for i in range(0, len(positions), 15):
            line_positions = positions[i:i+15]
            position_str = ", ".join(f"{pos:4d}" for pos in line_positions)
            text_lines.append(position_str)
        
        return "\n".join(text_lines)
    
    def _export_to_excel(self):
        """导出误码位置详细信息到Excel文件"""
        try:
            from PyQt5.QtWidgets import QFileDialog
            import pandas as pd
            from datetime import datetime
            
            # 选择保存文件路径
            default_filename = f"误码位置详情_帧{self.frame_index}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            file_path, _ = QFileDialog.getSaveFileName(
                self,
                "导出误码位置详情",
                default_filename,
                "Excel文件 (*.xlsx);;所有文件 (*.*)"
            )
            
            if not file_path:
                return
            
            # 创建Excel写入器
            with pd.ExcelWriter(file_path, engine='openpyxl') as writer:
                # 写入基本信息
                basic_info = {
                    '项目': ['帧序号', '误码位置总数', '比较范围'],
                    '值': [
                        self.frame_index,
                        len(self.error_positions) if self.error_positions else 0,
                        self._format_ranges(self.compare_ranges)
                    ]
                }
                basic_df = pd.DataFrame(basic_info)
                basic_df.to_excel(writer, sheet_name='基本信息', index=False)
                
                if self.error_positions and len(self.error_positions) > 0:
                    # 按比较范围分组导出
                    if self.compare_ranges:
                        for range_idx, (start_byte, end_byte) in enumerate(self.compare_ranges):
                            range_positions = [pos for pos in self.error_positions if start_byte <= pos <= end_byte]
                            if range_positions:
                                # 创建详细对比数据
                                comparison_data = []
                                for pos in sorted(range_positions):
                                    try:
                                        if (self.reference_frame and self.current_frame and 
                                            'payload' in self.reference_frame and 'payload' in self.current_frame and
                                            pos < len(self.reference_frame['payload']) and pos < len(self.current_frame['payload'])):
                                            
                                            ref_byte = self.reference_frame['payload'][pos]
                                            cur_byte = self.current_frame['payload'][pos]
                                            
                                            # 确保是整数类型
                                            if isinstance(ref_byte, bytes):
                                                ref_byte = ref_byte[0] if len(ref_byte) > 0 else 0
                                            if isinstance(cur_byte, bytes):
                                                cur_byte = cur_byte[0] if len(cur_byte) > 0 else 0
                                            
                                            xor_result = ref_byte ^ cur_byte
                                            
                                            # 计算错误比特数
                                            error_bits = bin(xor_result).count('1')
                                            
                                            comparison_data.append({
                                                '位置': pos,
                                                '标准值(十六进制)': f"0x{ref_byte:02X}",
                                                '标准值(十进制)': ref_byte,
                                                '标准值(二进制)': f"{ref_byte:08b}",
                                                '实际值(十六进制)': f"0x{cur_byte:02X}",
                                                '实际值(十进制)': cur_byte,
                                                '实际值(二进制)': f"{cur_byte:08b}",
                                                'XOR差异(十六进制)': f"0x{xor_result:02X}",
                                                'XOR差异(十进制)': xor_result,
                                                'XOR差异(二进制)': f"{xor_result:08b}",
                                                '错误比特数': error_bits
                                            })
                                        else:
                                            comparison_data.append({
                                                '位置': pos,
                                                '标准值(十六进制)': "N/A",
                                                '标准值(十进制)': "N/A",
                                                '标准值(二进制)': "N/A",
                                                '实际值(十六进制)': "N/A",
                                                '实际值(十进制)': "N/A",
                                                '实际值(二进制)': "N/A",
                                                'XOR差异(十六进制)': "N/A",
                                                'XOR差异(十进制)': "N/A",
                                                'XOR差异(二进制)': "N/A",
                                                '错误比特数': "N/A"
                                            })
                                    except Exception as e:
                                        comparison_data.append({
                                            '位置': pos,
                                            '标准值(十六进制)': f"错误: {str(e)}",
                                            '标准值(十进制)': "N/A",
                                            '标准值(二进制)': "N/A",
                                            '实际值(十六进制)': "N/A",
                                            '实际值(十进制)': "N/A",
                                            '实际值(二进制)': "N/A",
                                            'XOR差异(十六进制)': "N/A",
                                            'XOR差异(十进制)': "N/A",
                                            'XOR差异(二进制)': "N/A",
                                            '错误比特数': "N/A"
                                        })
                                
                                if comparison_data:
                                    df = pd.DataFrame(comparison_data)
                                    sheet_name = f"范围{range_idx + 1}({start_byte}-{end_byte})"
                                    # Excel工作表名称长度限制
                                    if len(sheet_name) > 31:
                                        sheet_name = f"范围{range_idx + 1}"
                                    df.to_excel(writer, sheet_name=sheet_name, index=False)
                    else:
                        # 如果没有范围信息，导出所有位置
                        all_positions_data = []
                        for pos in sorted(self.error_positions):
                            all_positions_data.append({'误码位置': pos})
                        
                        if all_positions_data:
                            df = pd.DataFrame(all_positions_data)
                            df.to_excel(writer, sheet_name='所有误码位置', index=False)
                
                # 添加统计信息工作表
                if self.error_positions:
                    stats_data = {
                        '统计项目': [
                            '总误码位置数',
                            '最小位置',
                            '最大位置',
                            '位置范围',
                            '平均位置',
                            '位置分布密度'
                        ],
                        '统计值': [
                            len(self.error_positions),
                            min(self.error_positions),
                            max(self.error_positions),
                            max(self.error_positions) - min(self.error_positions),
                            sum(self.error_positions) / len(self.error_positions),
                            f"{len(self.error_positions) / (max(self.error_positions) - min(self.error_positions) + 1):.4f}" if len(self.error_positions) > 1 else "1.0000"
                        ]
                    }
                    stats_df = pd.DataFrame(stats_data)
                    stats_df.to_excel(writer, sheet_name='统计信息', index=False)
            
            # 显示成功消息
            from PyQt5.QtWidgets import QMessageBox
            QMessageBox.information(
                self,
                "导出成功",
                f"误码位置详细信息已成功导出到:\n{file_path}\n\n"
                f"导出内容包括:\n"
                f"• 基本信息\n"
                f"• 按范围分组的详细对比数据\n"
                f"• 统计信息\n"
                f"• 完整的数据对比（十六进制、十进制、二进制格式）"
            )
            
        except ImportError:
            from PyQt5.QtWidgets import QMessageBox
            QMessageBox.critical(
                self,
                "导入错误",
                "导出Excel功能需要pandas和openpyxl库支持。\n"
                "请安装这些依赖：\n"
                "pip install pandas openpyxl"
            )
        except Exception as e:
            from PyQt5.QtWidgets import QMessageBox
            QMessageBox.critical(
                self,
                "导出失败",
                f"导出Excel文件时发生错误:\n{str(e)}"
            )

class ErrorRateWidget(QWidget):
    """误码率分析界面组件"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.layout = QVBoxLayout()  # 垂直布局
        self.setLayout(self.layout)
        # 移除布局的边距，避免空白区域
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        
        # 设置通用样式
        self.setStyleSheet("""
            QTableWidget {
                gridline-color: #DDDDDD;
                background-color: white;
                alternate-background-color: #E3F2FD;  /* 浅蓝色背景 */
                selection-background-color: #2196F3;  /* 选中时的深蓝色 */
                selection-color: white;
            }
            QHeaderView::section {
                background-color: #1976D2;  /* 深蓝色表头背景 */
                color: white;  /* 表头文字颜色 */
                padding: 6px;
                border: none;
                font-weight: bold;
            }
            QHeaderView::section:checked {
                background-color: #1565C0;  /* 选中时更深的蓝色 */
            }
            QGroupBox {
                border: 1px solid #BBBBBB;
                border-radius: 5px;
                margin-top: 10px;
                padding-top: 12px;
                font-weight: bold;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 5px;
            }
        """)
        
        self.logger = logging.getLogger('frame_analyzer')
        schema_file = get_resource_path('frame_schema.xml')
        self.frame_processor = FrameProcessor(schema_file)
        self.multi_format_processor = MultiFormatFrameProcessor()  # 添加多格式处理器
        self.frames = []  # 存储所有帧
        self.standard_frame = None  # 存储生成的标准帧
        
        # 分页变量
        self.current_page = 1
        self.page_size = 100  # 每页显示的条目数
        self.all_results = []  # 存储所有结果
        self.total_pages = 1
        
        # 存储当前分析结果的详细信息，用于弹窗显示
        self.current_analysis_results = None

        # 创建左侧控制面板
        left_panel = QWidget()
        left_layout = QVBoxLayout()
        left_panel.setLayout(left_layout)
        # 为左侧面板设置弹性尺寸策略
        left_panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # 文件选择区域
        file_group = QGroupBox("文件选择")
        file_layout = QVBoxLayout()  # 垂直布局

        # 帧文件格式选择（先于数据文件输入框）
        format_layout = QHBoxLayout()
        format_layout.addWidget(QLabel("帧文件格式:"))
        self.frame_format_combo = QComboBox()
        self.frame_format_combo.addItem("1092字节 - 完整帧格式")
        self.frame_format_combo.addItem("1024字节 - 数据帧格式")
        self.frame_format_combo.addItem("896字节 - 纯数据格式")
        self.frame_format_combo.setCurrentIndex(0)  # 默认选择1092字节
        self.frame_format_combo.currentTextChanged.connect(self._on_frame_format_changed)
        format_layout.addWidget(self.frame_format_combo)
        format_layout.addStretch()
        file_layout.addLayout(format_layout)

        file_path_layout = QHBoxLayout()
        file_path_layout.addWidget(QLabel("数据文件："))
        self.file_path = QLineEdit()
        self.file_path.setReadOnly(True)
        self.file_path.setPlaceholderText("选择数据文件")
        file_path_layout.addWidget(self.file_path)
        self.file_btn = QPushButton("浏览...")
        self.file_btn.clicked.connect(self._select_file)
        file_path_layout.addWidget(self.file_btn)
        file_layout.addLayout(file_path_layout)

        file_group.setLayout(file_layout)
        left_layout.addWidget(file_group)

        # 标准帧生成区域
        ref_frame_group = QGroupBox("标准帧生成")
        ref_frame_layout = QVBoxLayout()

        # 虚拟信道选择
        vc_select_layout = QHBoxLayout()
        vc_select_layout.addWidget(QLabel("选择虚拟信道:"))
        self.vc_select_combo = QComboBox()
        self.vc_select_combo.addItem("全部")
        self.vc_select_combo.setEnabled(False)
        vc_select_layout.addWidget(self.vc_select_combo)
        ref_frame_layout.addLayout(vc_select_layout)

        # 填充数据输入
        fill_layout = QHBoxLayout()
        fill_layout.addWidget(QLabel("填充数据（十六进制）："))
        self.fill_data_input = QLineEdit()
        self.fill_data_input.setPlaceholderText("输入填充数据，如：AA、55、00等")
        self.fill_data_input.setMaxLength(2)  # 限制为2个字符（1个字节）
        self.fill_data_input.textChanged.connect(self._validate_hex_input)
        fill_layout.addWidget(self.fill_data_input)
        
        # 生成标准帧按钮
        self.generate_frame_btn = QPushButton("生成标准帧")
        self.generate_frame_btn.clicked.connect(self._generate_standard_frame)
        fill_layout.addWidget(self.generate_frame_btn)
        ref_frame_layout.addLayout(fill_layout)

        # 标准帧信息显示
        self.frame_info = QLabel()
        self.frame_info.setWordWrap(True)
        self.frame_info.setStyleSheet("""
            QLabel {
                padding: 5px;
                background-color: #f8f9fa;
                border-radius: 3px;
                margin-top: 10px;
            }
        """)
        ref_frame_layout.addWidget(self.frame_info)

        ref_frame_group.setLayout(ref_frame_layout)
        left_layout.addWidget(ref_frame_group)

        # 比对选项区域
        options_group = QGroupBox("比对选项")
        options_layout = QVBoxLayout()

        # 移除原有帧文件格式选择（已上移）
        # 比对模式选择
        self.mode_data_only = QRadioButton("数据域(878字节,范围82-959)")
        self.mode_data_only.setChecked(True)
        options_layout.addWidget(self.mode_data_only)

        self.mode_header_data = QRadioButton("帧同步头+数据域(同步头:64-67字节,数据域:82-959字节)")
        options_layout.addWidget(self.mode_header_data)

        self.mode_custom = QRadioButton("自定义字节范围")
        options_layout.addWidget(self.mode_custom)

        # 自定义字节选择
        self.custom_bytes_widget = QWidget()
        custom_bytes_layout = QHBoxLayout(self.custom_bytes_widget)
        custom_bytes_layout.addWidget(QLabel("指定字节范围（0-1091）："))
        self.custom_bytes_input = QLineEdit()
        self.custom_bytes_input.setPlaceholderText("例如: 64-67,82-959")
        custom_bytes_layout.addWidget(self.custom_bytes_input)
        self.custom_bytes_widget.hide()
        options_layout.addWidget(self.custom_bytes_widget)

        options_group.setLayout(options_layout)
        left_layout.addWidget(options_group)

        # 添加比较按钮
        self.error_rate_button = QPushButton("开始分析")
        self.error_rate_button.setEnabled(False)
        self.error_rate_button.setStyleSheet("""
            QPushButton {
                background-color: #0064c8;
                color: white;
                border: none;
                padding: 10px 20px;
                font-size: 14px;
                font-weight: bold;
                border-radius: 5px;
                min-width: 150px;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
            QPushButton:hover:!disabled {
                background-color: #0055a5;
            }
            QPushButton:pressed:!disabled {
                background-color: #00448a;
            }
        """)
        left_layout.addWidget(self.error_rate_button)

        # 创建右侧结果显示面板
        right_panel = QWidget()
        right_layout = QVBoxLayout()
        right_panel.setLayout(right_layout)
        # 为右侧面板设置弹性尺寸策略
        right_panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # 结果显示区域
        results_group = QGroupBox("分析结果")
        results_layout = QVBoxLayout()

        self.results_text = QLabel()
        self.results_text.setWordWrap(True)
        self.results_text.setTextFormat(Qt.PlainText)  # 使用纯文本格式
        self.results_text.setMinimumHeight(350)  # 设置最小高度，确保摘要信息有足够空间
        self.results_text.setStyleSheet("""
            QLabel {
                font-size: 9pt;
                font-family: 'Consolas', 'Monaco', monospace;
                padding: 8px;
                background-color: #f8f9fa;
                border-radius: 5px;
                color: #333;
                border: 1px solid #DDD;
                line-height: 1.2;
            }
        """)
        results_layout.addWidget(self.results_text)

        # 添加结果表格
        self.results_table = QTableWidget()
        self.results_table.setColumnCount(9)  # 增加2列：比特错误率和错误比特数
        self.results_table.setHorizontalHeaderLabels(['帧序号', '虚拟信道帧计数', '虚拟信道', '字节错误率', '比特错误率', '错误字节数', '错误比特数', '总字节数', '误码位置(双击查看详情)'])
        # 设置表格为不可编辑状态
        self.results_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 启用交替行颜色
        self.results_table.setAlternatingRowColors(True)
        # 设置表格的大小策略，使其能够充分利用可用空间
        self.results_table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # 设置表格的高度限制
        self.results_table.setMinimumHeight(200)  # 最小高度
        self.results_table.setMaximumHeight(300)  # 最大高度，限制表格区域
        # 设置垂直滚动条策略
        self.results_table.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)  # 需要时显示垂直滚动条
        # 设置表格属性以适应内容，但误码位置列允许横向滚动
        self.results_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)  # 帧序号列
        self.results_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)  # 帧计数列
        self.results_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)  # 虚拟信道列
        self.results_table.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeToContents)  # 字节错误率列
        self.results_table.horizontalHeader().setSectionResizeMode(4, QHeaderView.ResizeToContents)  # 比特错误率列
        self.results_table.horizontalHeader().setSectionResizeMode(5, QHeaderView.ResizeToContents)  # 错误字节数列
        self.results_table.horizontalHeader().setSectionResizeMode(6, QHeaderView.ResizeToContents)  # 错误比特数列
        self.results_table.horizontalHeader().setSectionResizeMode(7, QHeaderView.ResizeToContents)  # 总字节数列
        self.results_table.horizontalHeader().setSectionResizeMode(8, QHeaderView.Interactive)  # 误码位置列可调整宽度
        # 设置误码位置列的最小宽度
        self.results_table.setColumnWidth(8, 200)
        self.results_table.setHorizontalScrollMode(QTableWidget.ScrollPerPixel)
        
        # 连接双击事件到误码位置详情显示
        self.results_table.cellDoubleClicked.connect(self._on_cell_double_clicked)
        
        # 设置表格的工具提示
        self.results_table.setToolTip("双击误码位置列可查看详细的误码位置信息和数据对比")
        
        results_layout.addWidget(self.results_table)
        
        # 添加分页控件
        pagination_widget = QWidget()
        pagination_layout = QHBoxLayout(pagination_widget)
        pagination_layout.setContentsMargins(0, 5, 0, 0)
        
        # 每页显示数量选择
        pagination_layout.addWidget(QLabel("每页显示:"))
        self.page_size_combo = QComboBox()
        self.page_size_combo.addItems(["20", "50", "100", "200", "500"])
        self.page_size_combo.setCurrentText("100")
        self.page_size_combo.currentTextChanged.connect(self._on_page_size_changed)
        pagination_layout.addWidget(self.page_size_combo)
        
        # 页码显示和控制
        pagination_layout.addStretch()
        self.prev_page_btn = QPushButton("上一页")
        self.prev_page_btn.setEnabled(False)
        self.prev_page_btn.clicked.connect(self._on_prev_page)
        pagination_layout.addWidget(self.prev_page_btn)
        
        self.page_info_label = QLabel("第 1 / 1 页")
        pagination_layout.addWidget(self.page_info_label)
        
        self.next_page_btn = QPushButton("下一页")
        self.next_page_btn.setEnabled(False)
        self.next_page_btn.clicked.connect(self._on_next_page)
        pagination_layout.addWidget(self.next_page_btn)
        
        # 跳转到页功能
        pagination_layout.addStretch()
        pagination_layout.addWidget(QLabel("跳转到:"))
        self.goto_page_input = QLineEdit()
        self.goto_page_input.setFixedWidth(50)
        self.goto_page_input.setValidator(QIntValidator(1, 9999))
        pagination_layout.addWidget(self.goto_page_input)
        self.goto_page_btn = QPushButton("确定")
        self.goto_page_btn.clicked.connect(self._on_goto_page)
        pagination_layout.addWidget(self.goto_page_btn)
        
        results_layout.addWidget(pagination_widget)

        results_group.setLayout(results_layout)
        right_layout.addWidget(results_group)

        # 创建分割器，允许用户调整左右面板的大小
        self.splitter = QSplitter(Qt.Horizontal)
        self.splitter.addWidget(left_panel)
        self.splitter.addWidget(right_panel)
        
        # 为分割器设置大小策略，使其填充整个可用空间
        self.splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        # 设置左右面板的初始宽度比例
        self.splitter.setSizes([400, 600])
        
        # 将分割器添加到主布局，确保其占据所有可用空间
        self.layout.addWidget(self.splitter, 1)  # 添加伸展因子1

        self.setLayout(self.layout)

        # 连接信号
        self.error_rate_button.clicked.connect(self._perform_error_rate_analysis)
        self.mode_custom.toggled.connect(lambda checked: self.custom_bytes_widget.setVisible(checked))
        self.file_path.textChanged.connect(self._on_file_selected)
        
        # 确保所有表格都是不可编辑的
        if hasattr(self, 'results_table'):
            self.results_table.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def _select_file(self):
        """选择文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            "选择数据文件",
            "",
            "帧数据文件 (*.raw *.dat);;XML文件 (*.xml);;所有文件 (*.*)"
        )
        if file_path:
            self.file_path.setText(file_path)

    def _on_file_selected(self):
        """处理文件选择事件"""
        try:
            if self.file_path.text():
                # 获取当前选择的帧格式
                frame_format = self._get_frame_format()
                
                # 创建进度对话框
                progress = ProgressDialog(self)
                progress.setWindowTitle(f"正在加载文件 ({frame_format}字节格式)")
                progress.show()

                # 根据帧格式选择不同的处理方式
                # 使用多格式处理器处理所有格式
                from PyQt5.QtCore import QThread, pyqtSignal
                
                class MultiFormatLoaderThread(QThread):
                    progress_signal = pyqtSignal(int, str, str)
                    finished_signal = pyqtSignal(list)
                    error_signal = pyqtSignal(str)
                    
                    def __init__(self, processor, file_path, frame_format):
                        super().__init__()
                        self.processor = processor
                        self.file_path = file_path
                        self.frame_format = frame_format
                        self._cancelled = False
                    
                    def cancel(self):
                        self._cancelled = True
                    
                    def run(self):
                        try:
                            if self._cancelled:
                                return
                            
                            def progress_callback(value, status, detail=""):
                                if self._cancelled:
                                    return
                                self.progress_signal.emit(value, status, detail)
                            
                            # 使用多格式处理器读取文件
                            frames = self.processor.read_frames_with_format(
                                self.file_path, 
                                self.frame_format, 
                                progress_callback
                            )
                            
                            if not self._cancelled:
                                self.finished_signal.emit(frames)
                                
                        except Exception as e:
                            if not self._cancelled:
                                self.error_signal.emit(str(e))
                
                # 为所有格式使用MultiFormatLoaderThread
                self.loader_thread = MultiFormatLoaderThread(
                    self.multi_format_processor, 
                    self.file_path.text(), 
                    frame_format
                )

                # 连接信号
                self.loader_thread.progress_signal.connect(
                    lambda value, status, detail: progress.update_progress(value, status, detail)
                )

                # 处理完成信号
                def on_load_finished(frames):
                    self.frames = frames
                    progress.update_progress(90, "更新界面显示...")
                    # 更新文件信息显示
                    if not hasattr(self, 'frame_info') or self.frame_info is None:
                        self.frame_info = QLabel()
                    
                    # 解析并填充虚拟信道列表
                    try:
                        # 对于所有格式，都正常提取虚拟信道信息
                        # 896字节格式实际上是1024字节格式去掉128字节RS校验码，仍包含虚拟信道
                        unique_vcs = sorted(set(frame.get('virtual_channel', 'N/A') for frame in self.frames))
                        self.vc_select_combo.setEnabled(True)
                        self.vc_select_combo.clear()
                        self.vc_select_combo.addItem("全部")
                        for vc in unique_vcs:
                            self.vc_select_combo.addItem(str(vc))
                    except Exception as e:
                        self.logger.error(f"填充虚拟信道下拉框失败: {str(e)}")
                    
                    # 显示文件加载信息
                    file_info = f"文件加载完成！\n"
                    file_info += f"帧格式: {frame_format}字节\n"
                    file_info += f"文件中共包含 {len(self.frames)} 帧数据\n"
                    if self.standard_frame is not None:
                        file_info += "标准帧已生成，可以开始分析"
                    else:
                        file_info += "请生成标准帧后开始分析"
                    
                    self.frame_info.setText(file_info)
                    
                    # 更新分析按钮状态
                    self._update_analysis_button_state()
                    
                    progress.update_progress(100, "数据加载完成")
                    # 延迟关闭进度对话框，确保界面渲染完成
                    progress.complete_and_close()

                # 处理错误信号
                def on_load_error(error_msg):
                    self.frames = []
                    progress.close()
                    QMessageBox.critical(self, "错误", f"读取文件失败: {error_msg}")

                # 处理取消操作
                def on_cancel_requested():
                    self.frames = []
                    self.loader_thread.cancel()

                # 连接信号
                self.loader_thread.finished_signal.connect(on_load_finished)
                self.loader_thread.error_signal.connect(on_load_error)
                progress.canceled.connect(on_cancel_requested)

                # 开始加载
                self.loader_thread.start()
            else:
                self.frames = []
                if hasattr(self, 'frame_info') and self.frame_info is not None:
                    self.frame_info.clear()
                self._update_analysis_button_state()

        except Exception as e:
            self.logger.error(f"读取文件失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"读取文件失败: {str(e)}")

    def _validate_hex_input(self, text):
        """验证十六进制输入"""
        # 只允许十六进制字符
        valid_chars = '0123456789ABCDEFabcdef'
        filtered_text = ''.join(c for c in text.upper() if c in valid_chars)
        
        if filtered_text != text.upper():
            self.fill_data_input.setText(filtered_text)
        
        # 更新生成按钮状态
        self.generate_frame_btn.setEnabled(len(filtered_text) > 0)

    def _generate_standard_frame(self):
        """生成标准帧数据"""
        try:
            fill_hex = self.fill_data_input.text().strip().upper()
            if not fill_hex:
                QMessageBox.warning(self, "警告", "请输入填充数据")
                return
            
            # 确保是2位十六进制数
            if len(fill_hex) == 1:
                fill_hex = '0' + fill_hex
            
            # 转换为字节值
            fill_byte = int(fill_hex, 16)
            
            # 获取当前选择的帧格式
            frame_format = self._get_frame_format()
            
            # 获取用户选择的虚拟信道
            selected_vc_text = self.vc_select_combo.currentText() if hasattr(self, 'vc_select_combo') else "全部"
            try:
                if selected_vc_text == "全部":
                    selected_vc = 63  # 默认空闲帧
                else:
                    selected_vc = int(selected_vc_text)
                    if not (0 <= selected_vc <= 63):
                        raise ValueError
            except ValueError:
                QMessageBox.warning(self, "警告", "虚拟信道选择不合法，已默认使用63 (空闲帧)")
                selected_vc = 63
            
            # 根据帧格式生成对应的标准帧
            if frame_format == "1092":
                frame_data = self._generate_1092_frame(fill_byte, selected_vc)
                info_text = (
                    f"标准帧生成成功！\n"
                    f"帧格式: 1092字节 - 完整帧格式\n"
                    f"帧同步头固定: 0x1ACFFC1D (字节64-67)\n"
                    f"虚拟信道: {selected_vc}\n"
                    f"填充数据: 0x{fill_hex}\n"
                    f"数据区填充: 字节68-1087 使用0x{fill_hex} 填充"
                )
                
            elif frame_format == "1024":
                frame_data = self._generate_1024_frame(fill_byte, selected_vc)
                info_text = (
                    f"标准帧生成成功！\n"
                    f"帧格式: 1024字节 - 数据帧格式\n"
                    f"帧同步头固定: 0x1ACFFC1D (字节0-3)\n"
                    f"虚拟信道: {selected_vc}\n"
                    f"填充数据: 0x{fill_hex}\n"
                    f"数据区填充: 字节18-895 使用0x{fill_hex} 填充"
                )
                
            elif frame_format == "896":
                frame_data = self._generate_896_frame(fill_byte)
                info_text = (
                    f"标准帧生成成功！\n"
                    f"帧格式: 896字节 - 无RS校验码格式\n"
                    f"帧同步头: 0x1ACFFC1D (字节0-3)\n"
                    f"虚拟信道: {selected_vc}\n"
                    f"填充数据: 0x{fill_hex}\n"
                    f"数据区填充: 字节18-895 使用0x{fill_hex} 填充"
                )
            else:
                raise ValueError(f"不支持的帧格式: {frame_format}")
            
            # 创建标准帧字典
            self.standard_frame = {
                'sync_word': 0x1ACFFC1D,  # 896字节格式也有帧同步头
                'frame_count': 0,
                'virtual_channel': selected_vc,  # 896字节格式也有虚拟信道
                'decode_status': 0,
                'payload': bytes(frame_data),
                'raw_frame': bytes(frame_data),  # 保存原始帧数据
                'frame_format': frame_format,  # 添加格式标识
                'frame_len': len(frame_data),
                'frame_sync_status': 1,
                'bit_slip_status': 0,
                '帧检验结果': 0,
                '同步字状态': 0
            }
            
            self.frame_info.setText(info_text)
            
            # 更新分析按钮状态
            self._update_analysis_button_state()
            
            self.logger.info(f"生成{frame_format}字节标准帧成功，填充数据: 0x{fill_hex}")
            
        except Exception as e:
            self.logger.error(f"生成标准帧失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"生成标准帧失败: {str(e)}")

    def _generate_1092_frame(self, fill_byte, selected_vc):
        """生成1092字节格式的标准帧"""
        frame_data = bytearray(1092)
        
        # 帧头(0-3): 固定值1234567890
        frame_data[0:4] = struct.pack('>I', 1234567890)
        
        # 全帧长度(4-7): 固定值1092
        frame_data[4:8] = struct.pack('>I', 1092)
        
        # 保留字节1(8-11): 值为0
        frame_data[8:12] = struct.pack('>I', 0)
        
        # 时间标签(12-15): 从2000年1月1日起的积日，设为固定值8000
        frame_data[12:16] = struct.pack('>I', 8000)
        
        # 毫秒计数(16-19): 设为固定值500
        frame_data[16:20] = struct.pack('>I', 500)
        
        # 帧计数(20-23): 设为固定值0
        frame_data[20:24] = struct.pack('>I', 0)
        
        # 帧检验结果(24-27): 默认为0表示正确
        frame_data[24:28] = struct.pack('>I', 0)
        
        # 帧同步状态(28-31): 默认为1表示同步且锁定
        frame_data[28:32] = struct.pack('>I', 1)
        
        # 位滑状态(32-35): 默认为0表示无位滑
        frame_data[32:36] = struct.pack('>I', 0)
        
        # 保留字节2(36-39): 值为0
        frame_data[36:40] = struct.pack('>I', 0)
        
        # VCDU数据区长度(40-43): 1024字节
        frame_data[40:44] = struct.pack('>I', 1024)
        
        # 同步字长度(44-47): 默认32bit
        frame_data[44:48] = struct.pack('>I', 32)
        
        # 帧检验&译码状态(48-51): 默认为0
        frame_data[48:52] = struct.pack('>I', 0)
        
        # 帧校验及同步字状态(52-55): 默认为0
        frame_data[52:56] = struct.pack('>I', 0)
        
        # 保留字节3(56-59): 值为0
        frame_data[56:60] = struct.pack('>I', 0)
        
        # 保留字节4(60-63): 值为0
        frame_data[60:64] = struct.pack('>I', 0)
        
        # === 正确的VCDU数据区结构（64-1087，共1024字节）===
        # 帧同步头(64-67): 4字节，固定值 0x1ACFFC1D
        frame_data[64:68] = struct.pack('>I', 0x1ACFFC1D)
        
        # 版本号+航天器标识(68): 1字节，版本号01 + 航天器标识54H
        frame_data[68] = (0x01 << 6) | (0x54 & 0x3F)  # 版本号(高2位) + 航天器标识(低6位)
        
        # 虚拟信道标识(69): 1字节，低6位
        frame_data[69] = selected_vc & 0x3F
        
        # 虚拟信道帧计数(70-72): 3字节，设为0
        frame_data[70:73] = struct.pack('>I', 0)[1:4]  # 取后3字节
        
        # 标志域(73): 1字节，设为0
        frame_data[73] = 0x00
        
        # 插入域(74-81): 8字节，设为0
        frame_data[74:82] = bytes([0x00] * 8)
        
        # 数据域(82-959): 878字节，使用用户指定的填充数据
        for i in range(82, 960):
            frame_data[i] = fill_byte
        
        # RS校验码(960-1087): 128字节，设为0
        frame_data[960:1088] = bytes([0x00] * 128)
        # 帧尾(1088-1091): 固定值-1234567890
        frame_data[1088:1092] = struct.pack('>i', -1234567890)
        
        # === 调试打印：1092字节格式标准帧生成 ===
        print(f"\n=== 调试信息：1092字节格式标准帧生成 ===")
        print(f"总帧长度: {len(frame_data)} 字节")
        print(f"VCDU数据区位置: 字节64-1087 (1024字节)")
        print(f"帧同步头位置: 字节64-67")
        print(f"数据域比较范围: 字节82-959 (878字节)")
        print(f"虚拟信道: {selected_vc}")
        print(f"填充数据: 0x{fill_byte:02X}")
        
        # 显示帧同步头
        sync_head = frame_data[64:68]
        sync_hex = ' '.join(f'{b:02X}' for b in sync_head)
        print(f"帧同步头(64-67): {sync_hex}")
        
        # 显示VCID位置的值
        vcid_byte = frame_data[69]  # 第6个字节（从64开始计）
        print(f"VCID字节(69): 0x{vcid_byte:02X} (虚拟信道: {vcid_byte & 0x3F})")
        
        # 显示数据域前32字节
        data_start = 82
        data_sample = frame_data[data_start:data_start+32]
        data_hex = ' '.join(f'{b:02X}' for b in data_sample)
        print(f"数据域前32字节(82-113): {data_hex}")
        
        # 显示数据域后32字节
        data_end = 959
        data_sample_end = frame_data[data_end-31:data_end+1]
        data_hex_end = ' '.join(f'{b:02X}' for b in data_sample_end)
        print(f"数据域后32字节(928-959): {data_hex_end}")
        
        print("=== 标准帧生成调试信息结束 ===\n")
        
        return frame_data

    def _generate_1024_frame(self, fill_byte, selected_vc):
        """生成1024字节格式的标准帧"""
        frame_data = bytearray(1024)
        
        # 帧同步头(0-3): 固定值 0x1ACFFC1D
        frame_data[0:4] = struct.pack('>I', 0x1ACFFC1D)
        
        # 版本号(2bit) + 航天器标识(8bit) - 字节4
        frame_data[4] = (0x01 << 6) | (54 & 0x3F)  # 版本号(高2位) + 航天器标识(低6位)
        
        # 虚拟信道标识(低6位) - 字节5
        frame_data[5] = selected_vc & 0x3F
        
        # 虚拟信道帧计数（3字节） - 字节6-8
        frame_data[6:9] = struct.pack('>I', 0)[1:4]  # 取后3字节，计数为0
        
        # 标志域(1字节) - 字节9
        frame_data[9] = 0x00
        
        # 插入域(8字节) - 字节10-17
        frame_data[10:18] = bytes([0x00] * 8)
        
        # 数据域(878字节) - 字节18-895，使用填充数据
        for i in range(18, 896):
            frame_data[i] = fill_byte
        
        # RS校验码(128字节) - 字节896-1023，简化为全0
        frame_data[896:1024] = bytes([0x00] * 128)
        
        return frame_data

    def _generate_896_frame(self, fill_byte):
        """生成896字节格式的标准帧（1024字节去掉128字节RS校验码）"""
        frame_data = bytearray(896)
        
        # 896字节格式实际上是1024字节格式的前896字节
        # 帧同步头(0-3): 固定值 0x1ACFFC1D
        frame_data[0:4] = struct.pack('>I', 0x1ACFFC1D)
        
        # 版本号(2bit) + 航天器标识(8bit) - 字节4
        frame_data[4] = (0x01 << 6) | (54 & 0x3F)  # 版本号(高2位) + 航天器标识(低6位)
        
        # 虚拟信道标识(低6位) - 字节5
        # 从用户选择的虚拟信道获取
        selected_vc_text = self.vc_select_combo.currentText() if hasattr(self, 'vc_select_combo') else "全部"
        try:
            if selected_vc_text == "全部":
                selected_vc = 63  # 默认空闲帧
            else:
                selected_vc = int(selected_vc_text)
                if not (0 <= selected_vc <= 63):
                    selected_vc = 63
        except ValueError:
            selected_vc = 63
        
        frame_data[5] = selected_vc & 0x3F
        
        # 虚拟信道帧计数（3字节） - 字节6-8
        frame_data[6:9] = struct.pack('>I', 0)[1:4]  # 取后3字节，计数为0
        
        # 标志域(1字节) - 字节9
        frame_data[9] = 0x00
        
        # 插入域(8字节) - 字节10-17
        frame_data[10:18] = bytes([0x00] * 8)
        
        # 数据域(878字节) - 字节18-895，使用填充数据
        for i in range(18, 896):
            frame_data[i] = fill_byte
        
        return frame_data

    def _update_analysis_button_state(self):
        """更新分析按钮状态"""
        # 只有当文件已加载且标准帧已生成时才启用分析按钮
        self.error_rate_button.setEnabled(
            len(self.frames) > 0 and self.standard_frame is not None
        )

    def _get_compare_ranges(self):
        """获取要比较的字节范围"""
        frame_format = self._get_frame_format()
        
        if self.mode_data_only.isChecked():
            # 数据域范围根据帧格式确定
            if frame_format == "1092":
                return [(82, 959)]  # 1092字节格式：数据域82-959
            elif frame_format == "1024":
                return [(18, 895)]  # 1024字节格式：数据域18-895
            elif frame_format == "896":
                return [(18, 895)]  # 896字节格式：数据域18-895（与1024字节格式相同）
                
        elif self.mode_header_data.isChecked():
            # 帧同步头+数据域范围根据帧格式确定
            if frame_format == "1092":
                return [(64, 67), (82, 959)]  # 1092字节格式：同步头64-67，数据域82-959
            elif frame_format == "1024":
                return [(0, 3), (18, 895)]    # 1024字节格式：同步头0-3，数据域18-895
            elif frame_format == "896":
                # 896字节格式与1024字节格式前896字节相同，有帧同步头
                return [(0, 3), (18, 895)]    # 896字节格式：同步头0-3，数据域18-895
                
        elif self.mode_custom.isChecked():
            # 自定义范围
            custom_text = self.custom_bytes_input.text().strip()
            if not custom_text:
                return []

            try:
                ranges = []
                # 解析逗号分隔的范围表达式
                for range_text in custom_text.split(','):
                    if '-' in range_text:
                        start, end = map(int, range_text.split('-'))
                        
                        # 根据帧格式验证范围
                        max_byte = 1091 if frame_format == "1092" else (1023 if frame_format == "1024" else 895)
                        
                        if 0 <= start <= max_byte and 0 <= end <= max_byte and start <= end:
                            ranges.append((start, end))
                        else:
                            self.logger.warning(f"字节范围 {start}-{end} 超出了{frame_format}字节格式的有效范围(0-{max_byte})")
                            
                return ranges
            except Exception as e:
                self.logger.error(f"解析自定义字节范围时发生错误: {str(e)}")
                return []

        return []

    def _perform_error_rate_analysis(self):
        """执行误码率分析"""
        try:
            # 验证是否生成了标准帧
            if self.standard_frame is None:
                QMessageBox.warning(self, "警告", "请先生成标准帧")
                return

            # 创建进度对话框
            progress = ProgressDialog(self)
            progress.setWindowTitle("误码率分析")
            progress.show()

            try:
                # 获取比较范围
                compare_ranges = self._get_compare_ranges()
                if not compare_ranges:
                    QMessageBox.warning(self, "警告", "请选择有效的比较范围")
                    progress.close()
                    return

                # 获取标准帧
                reference_frame = self.standard_frame
                reference_vc = reference_frame['virtual_channel']

                # 根据用户选择的虚拟信道过滤帧
                selected_vc_text = self.vc_select_combo.currentText() if hasattr(self, 'vc_select_combo') else "全部"
                if selected_vc_text != "全部":
                    try:
                        selected_vc = int(selected_vc_text)
                        analysis_frames = [f for f in self.frames if f.get('virtual_channel') == selected_vc]
                        if not analysis_frames:
                            QMessageBox.information(self, "提示", f"在文件中未找到虚拟信道 VC{selected_vc} 的帧数据")
                            progress.close()
                            return
                    except ValueError:
                        analysis_frames = self.frames  # 解析失败时回退到全部
                else:
                    analysis_frames = self.frames

                # 后续显示已选择的虚拟信道信息
                vc_info_text = f"已选择虚拟信道: {selected_vc_text}"

                progress.update_progress(10, "开始误码率分析...")
                progress.update_progress(12, vc_info_text)

                # 确保UI更新
                QApplication.processEvents()

                # 估算处理时间和批处理大小
                total_frames = len(analysis_frames)
                # 根据帧数动态调整批次大小
                batch_size = 1
                if total_frames > 1000000:  # 超过100万帧
                    batch_size = 1000
                elif total_frames > 100000:
                    batch_size = 500
                elif total_frames > 10000:
                    batch_size = 200
                elif total_frames > 1000:
                    batch_size = 50
                elif total_frames > 500:
                    batch_size = 20
                elif total_frames > 100:
                    batch_size = 10
                
                # 预先创建帧的原始索引映射表，提高查找效率
                # 使用id(frame)作为键，可以快速查找帧在原始帧列表中的索引
                frame_to_index = {id(frame): i for i, frame in enumerate(self.frames)}
                
                progress.update_progress(15, f"准备分析 {total_frames} 个帧...", f"标准帧虚拟信道: {reference_vc}")
                QApplication.processEvents()  # 确保UI更新
                
                # 对每一帧计算误码率
                results = []  # 结果列表
                original_indices = []  # 原始索引列表
                
                # 处理进度信息
                last_ui_update_time = time.time()
                processed_frames = 0
                frames_with_errors = 0  # 记录有差异的帧数量
                
                # 批处理方式处理帧
                for batch_start in range(0, total_frames, batch_size):
                    # 检查是否取消操作
                    if progress.is_cancelled:
                        raise Exception("操作已取消")
                    
                    # 计算当前批次的结束位置
                    batch_end = min(batch_start + batch_size, total_frames)
                    current_batch_size = batch_end - batch_start
                    
                    # 处理当前批次的所有帧
                    for idx in range(batch_start, batch_end):
                        # 获取当前帧
                        frame = analysis_frames[idx]
                        
                        # 跳过标准帧自身
                        if id(frame) == id(reference_frame):
                            continue
                        
                        # 查找此帧在原始数据中的索引
                        original_idx = frame_to_index.get(id(frame))
                        if original_idx is not None:
                            original_indices.append(original_idx)
                        else:
                            # 如果找不到索引，使用当前批次的处理位置作为替代值
                            original_indices.append(idx)
                            
                        # 计算误码率 - 优化比较逻辑，同时计算字节和比特错误
                        error_count = 0  # 错误字节数
                        error_bit_count = 0  # 错误比特数
                        error_positions = []
                        
                        for byte_range in compare_ranges:
                            raw_start_byte, raw_end_byte = byte_range # 这是原始帧的绝对偏移

                            # --- 新增逻辑：使用raw_frame（原始帧数据）而不是payload ---
                            # 检查是否有raw_frame字段
                            if 'raw_frame' in reference_frame and 'raw_frame' in frame:
                                # 确保不超出数据范围
                                ref_raw_frame = reference_frame['raw_frame']
                                frame_raw_frame = frame['raw_frame']
                                
                                # 确保结束位置不超出帧长度
                                effective_end_byte = min(raw_end_byte, 
                                                       len(ref_raw_frame) - 1, 
                                                       len(frame_raw_frame) - 1)
                                
                                if raw_start_byte > effective_end_byte:
                                    continue
                                
                                # 直接从原始帧数据中提取
                                ref_data = ref_raw_frame[raw_start_byte : effective_end_byte + 1]
                                frame_data = frame_raw_frame[raw_start_byte : effective_end_byte + 1]
                                
                                # === 调试打印：1092字节格式数据域提取 ===
                                if frame.get('frame_format') == '1092' and idx < 3:  # 只打印前3帧
                                    print(f"\n=== 调试信息：1092字节格式第{idx}帧数据域提取 ===")
                                    print(f"比较范围: {raw_start_byte}-{raw_end_byte} (实际使用: {raw_start_byte}-{effective_end_byte})")
                                    print(f"数据长度: 标准帧{len(ref_data)}字节, 分析帧{len(frame_data)}字节")
                                    
                                    # 显示VCDU数据区开始部分 (字节64-95，共32字节)
                                    vcdu_start = frame_raw_frame[64:96]
                                    vcdu_hex = ' '.join(f'{b:02X}' for b in vcdu_start)
                                    print(f"VCDU数据区前32字节(64-95): {vcdu_hex}")
                                    
                                    # 显示更大范围的数据，从字节64到120 (56字节)
                                    extended_data = frame_raw_frame[64:120]
                                    print(f"扩展范围(64-119)共56字节:")
                                    for i in range(0, len(extended_data), 16):
                                        chunk = extended_data[i:i+16]
                                        hex_str = ' '.join(f'{b:02X}' for b in chunk)
                                        offset = 64 + i
                                        print(f"  偏移{offset:3d}-{offset+len(chunk)-1:3d}: {hex_str}")
                                    
                                    # 打印前32字节的十六进制值
                                    if len(ref_data) >= 32:
                                        ref_hex = ' '.join(f'{b:02X}' for b in ref_data[:32])
                                        frame_hex = ' '.join(f'{b:02X}' for b in frame_data[:32])
                                        print(f"标准帧前32字节: {ref_hex}")
                                        print(f"分析帧前32字节: {frame_hex}")
                                        
                                        # 显示差异位置
                                        diff_positions = [i for i in range(min(32, len(ref_data), len(frame_data))) 
                                                        if ref_data[i] != frame_data[i]]
                                        if diff_positions:
                                            print(f"前32字节中的差异位置: {diff_positions}")
                                        else:
                                            print("前32字节完全一致")
                                    
                                    # 尝试显示不同位置的数据，看是否能找到BES显示的数据
                                    print(f"尝试不同的数据域起始位置:")
                                    test_positions = [64+10, 64+18, 64+20, 82, 85, 90]  # 测试几个可能的位置
                                    for test_pos in test_positions:
                                        if test_pos + 32 <= len(frame_raw_frame):
                                            test_data = frame_raw_frame[test_pos:test_pos+32]
                                            test_hex = ' '.join(f'{b:02X}' for b in test_data)
                                            print(f"  位置{test_pos}-{test_pos+31}: {test_hex}")
                                    
                                    # 打印最后32字节的十六进制值
                                    if len(ref_data) >= 64:
                                        ref_hex_end = ' '.join(f'{b:02X}' for b in ref_data[-32:])
                                        frame_hex_end = ' '.join(f'{b:02X}' for b in frame_data[-32:])
                                        print(f"标准帧后32字节: {ref_hex_end}")
                                        print(f"分析帧后32字节: {frame_hex_end}")
                                        
                                        # 显示差异位置
                                        start_pos = len(ref_data) - 32
                                        diff_positions = [start_pos + i for i in range(32) 
                                                        if ref_data[start_pos + i] != frame_data[start_pos + i]]
                                        if diff_positions:
                                            print(f"后32字节中的差异位置: {diff_positions}")
                                        else:
                                            print("后32字节完全一致")
                                    print("=== 调试信息结束 ===\n")
                            else:
                                # 兼容旧版本：如果没有raw_frame，使用原来的逻辑
                                self.logger.warning("帧数据中没有raw_frame字段，使用payload字段")
                                
                                current_frame_format = frame.get('frame_format', '1092')
                                # 对于1092格式，需要调整偏移
                                if current_frame_format == '1092':
                                    payload_slice_start_byte = raw_start_byte - 64
                                    payload_slice_end_byte = raw_end_byte - 64
                                else:
                                    payload_slice_start_byte = raw_start_byte
                                    payload_slice_end_byte = raw_end_byte
                                
                                payload_slice_start_byte = max(0, payload_slice_start_byte)
                                
                                # 确保不超出payload范围
                                len_reference_payload = len(reference_frame['payload'])
                                len_frame_payload = len(frame['payload'])
                                effective_end_byte = min(payload_slice_end_byte, len_reference_payload - 1, len_frame_payload - 1)
                                
                                if payload_slice_start_byte > effective_end_byte:
                                    continue
                                
                                ref_data = reference_frame['payload'][payload_slice_start_byte : effective_end_byte + 1]
                                frame_data = frame['payload'][payload_slice_start_byte : effective_end_byte + 1]
                            
                            # 检查数据长度是否一致
                            min_length = min(len(ref_data), len(frame_data))
                            
                            # 检查是否为NumPy数组，使用不同的比较方法
                            if hasattr(ref_data, 'tobytes') and hasattr(frame_data, 'tobytes'):
                                # NumPy数组比较
                                for offset in range(min_length):
                                    ref_byte = ref_data[offset]
                                    frame_byte = frame_data[offset]
                                    
                                    if ref_byte != frame_byte:
                                        error_count += 1
                                        # 计算错误比特数：对每个错误字节，通过异或操作计算不同的比特数
                                        xor_result = ref_byte ^ frame_byte
                                        error_bits = bin(xor_result).count('1')  # 计算1的个数即为错误比特数
                                        error_bit_count += error_bits
                                        
                                        # 限制误码位置的数量，避免过多数据影响性能
                                        if len(error_positions) < 500:  # 最多记录500个误码位置
                                            error_positions.append(raw_start_byte + offset)
                            else:
                                # 字节比较
                                for offset in range(min_length):
                                    try:
                                        # 提取字节值（处理不同数据类型）
                                        ref_byte = ref_data[offset]
                                        frame_byte = frame_data[offset]
                                        
                                        # 转换为整数进行比较
                                        ref_value = ref_byte if isinstance(ref_byte, int) else ord(ref_byte)
                                        frame_value = frame_byte if isinstance(frame_byte, int) else ord(frame_byte)
                                        
                                        if ref_value != frame_value:
                                            error_count += 1
                                            # 计算错误比特数：对每个错误字节，通过异或操作计算不同的比特数
                                            xor_result = ref_value ^ frame_value
                                            error_bits = bin(xor_result).count('1')  # 计算1的个数即为错误比特数
                                            error_bit_count += error_bits
                                            
                                            # 限制误码位置的数量
                                            if len(error_positions) < 500:
                                                error_positions.append(raw_start_byte + offset)
                                    except Exception as e:
                                        self.logger.error(f"比较字节时出错: {str(e)}")
                                        continue

                        # 计算误码率和误比特率
                        total_bytes = 0
                        for start, end in compare_ranges:
                            # 确保范围在有效范围内
                            start = max(0, start)
                            end = min(end, 
                                     min(len(reference_frame['payload'])-1, len(frame['payload'])-1))
                            if start <= end:
                                total_bytes += (end - start + 1)
                                
                        total_bits = total_bytes * 8  # 总比特数
                        error_rate = error_count / total_bytes if total_bytes > 0 else 0  # 字节错误率
                        bit_error_rate = error_bit_count / total_bits if total_bits > 0 else 0  # 比特错误率

                        # 只添加有差异的帧到结果列表中
                        if error_count > 0:
                            frames_with_errors += 1
                            results.append({
                                'frame_index': len(original_indices) - 1,  # 在原始索引列表中的位置
                                'error_rate': error_rate,  # 字节错误率
                                'bit_error_rate': bit_error_rate,  # 比特错误率
                                'error_bytes': error_count,  # 错误字节数
                                'error_bits': error_bit_count,  # 错误比特数
                                'total_bytes': total_bytes,  # 总字节数
                                'total_bits': total_bits,  # 总比特数
                                'error_positions': error_positions,
                                'virtual_channel': frame.get('virtual_channel', 'N/A')  # 添加虚拟信道信息
                            })
                    
                    # 更新处理进度
                    processed_frames += current_batch_size
                    
                    # 计算进度并更新UI
                    analysis_progress = int(15 + (processed_frames / total_frames) * 75)
                    current_time = time.time()
                    
                    # 每批次或每100ms更新一次UI
                    if current_time - last_ui_update_time > 0.1:
                        progress.update_progress(
                            analysis_progress,
                            f"分析帧 {processed_frames}/{total_frames}",
                            f"已找到 {frames_with_errors} 个有差异的帧"
                        )
                        QApplication.processEvents()  # 确保UI更新
                        last_ui_update_time = current_time
                
                progress.update_progress(90, "正在生成分析报告...")
                QApplication.processEvents()  # 确保UI更新

                # 限制结果数量，避免处理过多数据导致界面卡死
                max_display_results = 1000
                if len(results) > max_display_results:
                    # 排序结果，按误码率从高到低，然后取前max_display_results个
                    results.sort(key=lambda x: x['error_rate'], reverse=True)
                    truncated_results = results[:max_display_results]
                    # 更新提示信息
                    progress.update_progress(92, f"发现{len(results)}个差异帧，显示误码率最高的{max_display_results}个")
                    
                    # 计算每帧字节数
                    total_bytes_per_frame = 0
                    for start, end in compare_ranges:
                        # 确保范围在有效范围内
                        start = max(0, start)
                        end = min(end, 1091)  # 假设帧最大长度为1092字节
                        if start <= end:
                            total_bytes_per_frame += (end - start + 1)
                    
                    # 保存完整的结果，但只显示部分
                    display_results = {
                        'reference_frame_index': -1,  # 标准帧不在原始帧列表中
                        'reference_frame': reference_frame,  # 传递完整的参考帧
                        'compare_ranges': compare_ranges,
                        'frame_results': truncated_results,
                        'original_indices': original_indices,
                        'total_analyzed_frames': total_frames,
                        'total_error_frames': frames_with_errors,
                        'truncated': True,
                        'total_results': len(results),
                        'total_bytes_per_frame': total_bytes_per_frame  # 添加每帧字节数信息
                    }
                else:
                    # 排序结果，按误码率从高到低
                    results.sort(key=lambda x: x['error_rate'], reverse=True)
                    
                    # 计算每帧字节数
                    total_bytes_per_frame = 0
                    for start, end in compare_ranges:
                        # 确保范围在有效范围内
                        start = max(0, start)
                        end = min(end, 1091)  # 假设帧最大长度为1092字节
                        if start <= end:
                            total_bytes_per_frame += (end - start + 1)
                    
                    # 所有结果都能显示
                    display_results = {
                        'reference_frame_index': -1,  # 标准帧不在原始帧列表中
                        'reference_frame': reference_frame,  # 传递完整的参考帧
                        'compare_ranges': compare_ranges,
                        'frame_results': results,
                        'original_indices': original_indices,
                        'total_analyzed_frames': total_frames,
                        'total_error_frames': frames_with_errors,
                        'truncated': False,
                        'total_bytes_per_frame': total_bytes_per_frame  # 添加每帧字节数信息
                    }
                
                QApplication.processEvents()  # 确保UI更新
                
                # 确保界面对象仍然有效
                if hasattr(self, 'results_text') and hasattr(self, 'results_table'):
                    progress.update_progress(95, "显示分析结果...")
                    QApplication.processEvents()  # 确保UI更新
                    
                    # 显示结果
                    try:
                        self._display_error_rate_results(display_results, reference_vc)
                        
                        progress.update_progress(100, "误码率分析完成")
                        QApplication.processEvents()  # 确保UI更新最终状态
                    except Exception as display_error:
                        self.logger.error(f"显示结果时出错: {str(display_error)}", exc_info=True)
                        QMessageBox.critical(self, "错误", f"显示结果时出错: {str(display_error)}")
                else:
                    self.logger.warning("误码率分析完成但界面对象已被销毁，无法显示结果")

            except Exception as e:
                if str(e) == "操作已取消":
                    self.logger.info("用户取消了误码率分析")
                    return
                else:
                    raise
            finally:
                # 确保进度对话框被关闭
                if hasattr(progress, 'isVisible') and progress.isVisible():
                    # 延迟关闭进度对话框，确保界面渲染完成
                    progress.complete_and_close()

        except Exception as e:
            self.logger.error(f"执行误码率分析失败: {str(e)}", exc_info=True)
            traceback.print_exc()  # 打印完整的异常堆栈跟踪
            QMessageBox.critical(self, "错误", f"执行误码率分析失败: {str(e)}")

    def _display_error_rate_results(self, results, reference_vc):
        """显示误码率分析结果"""
        try:
            # 保存所有结果便于分页
            self.all_results = results.get('frame_results', [])
            
            # 保存当前分析结果的详细信息，用于弹窗显示
            self.current_analysis_results = results
            
            # 获取总分析帧数和有差异的帧数
            total_analyzed_frames = results.get('total_analyzed_frames', len(self.all_results))
            total_error_frames = results.get('total_error_frames', len(self.all_results))
            
            # 计算每个范围的总字节数
            total_bytes_per_frame = results.get('total_bytes_per_frame', 0)
            
            # 计算总的比特数、错误比特数和比特错误率
            total_bits_per_frame = total_bytes_per_frame * 8  # 每帧的总比特数
            total_bits_all = total_bits_per_frame * total_analyzed_frames  # 总比特数（所有帧）
            total_error_bits = 0  # 总错误比特数
            total_error_bytes = 0  # 总错误字节数
            
            # 统计所有错误帧的比特和字节错误
            for result in self.all_results:
                total_error_bits += result.get('error_bits', 0)
                total_error_bytes += result.get('error_bytes', 0)
            
            # 计算错误率
            bit_error_rate = total_error_bits / total_bits_all if total_bits_all > 0 else 0
            byte_error_rate = total_error_bytes / (total_bytes_per_frame * total_analyzed_frames) if total_analyzed_frames > 0 else 0
            frame_error_rate = total_error_frames / total_analyzed_frames if total_analyzed_frames > 0 else 0
            
            # 判断是否有截断的结果
            is_truncated = results.get('truncated', False)
            total_results = results.get('total_results', len(self.all_results))
            
            # 重置分页
            self.current_page = 1
            self.page_size = int(self.page_size_combo.currentText())
            self.total_pages = (len(self.all_results) + self.page_size - 1) // self.page_size if len(self.all_results) > 0 else 1
            
            # 生成比较范围描述
            range_desc = []
            for start, end in results['compare_ranges']:
                range_desc.append(f"{start}-{end}")
                
            # 获取标准帧信息
            ref_frame = results.get('reference_frame', {})
            ref_frame_count_hex = format_hex_with_space(ref_frame.get('frame_count', 0))
            fill_data_hex = self.fill_data_input.text().strip().upper()
            if len(fill_data_hex) == 1:
                fill_data_hex = '0' + fill_data_hex

            # 显示摘要信息 - 使用更紧凑的格式
            summary = (
                f"【标准帧】VC:{reference_vc} | 帧计数:{ref_frame_count_hex} | 填充:0x{fill_data_hex} | "
                f"比较范围:{', '.join(range_desc)} | 每帧:{total_bytes_per_frame}字节/{total_bits_per_frame}比特\n"
                f"{'─' * 100}\n"
                f"【帧统计】总数:{total_analyzed_frames:,} | 错误:{total_error_frames:,} | "
                f"错误率:{frame_error_rate:.6f} ({total_error_frames}/{total_analyzed_frames})\n"
                f"【字节统计】总数:{total_bytes_per_frame * total_analyzed_frames:,} | "
                f"错误:{total_error_bytes:,} | 错误率:{byte_error_rate:.8f}\n"
                f"【比特统计】总数:{total_bits_all:,} | 错误:{total_error_bits:,} | "
                f"错误率:{bit_error_rate:.10f}\n"
                f"{'─' * 100}"
            )
            
            # 添加结果显示说明
            if len(self.all_results) == 0:
                summary += f"\n注意：所有帧都与标准帧完全一致，无差异帧"
            elif is_truncated:
                summary += f"\n注意：找到{total_results}个差异帧，已按误码率排序，通过分页查看前{len(self.all_results)}个"
            elif len(self.all_results) > self.page_size:
                summary += f"\n注意：共有{len(self.all_results)}个差异帧，已按误码率排序，通过分页查看"
            else:
                summary += f"\n注意：仅显示有差异的帧，共{len(self.all_results)}帧"
            
            # 检查对象是否仍然有效
            if hasattr(self, 'results_text') and self.results_text is not None:
                self.results_text.setText(summary)
            
            # 确保表格对象有效
            if not hasattr(self, 'results_table') or self.results_table is None:
                return

            # 更新分页控件状态
            self._update_pagination_controls()
            
            # 加载当前页的数据
            if len(self.all_results) > 0:
                self._load_current_page_data(results)
            else:
                # 无差异帧时清空表格
                self.results_table.setRowCount(0)
            
        except Exception as e:
            self.logger.error(f"显示误码率分析结果失败: {str(e)}", exc_info=True)
            # 显示错误消息给用户
            QMessageBox.critical(self, "错误", f"显示误码率分析结果失败: {str(e)}")
            
    def _update_pagination_controls(self):
        """更新分页控件的状态"""
        self.page_info_label.setText(f"第 {self.current_page} / {self.total_pages} 页")
        self.prev_page_btn.setEnabled(self.current_page > 1)
        self.next_page_btn.setEnabled(self.current_page < self.total_pages)
        
    def _load_current_page_data(self, results):
        """加载当前页的数据到表格"""
        try:
            # 计算当前页的数据索引范围
            start_idx = (self.current_page - 1) * self.page_size
            end_idx = min(start_idx + self.page_size, len(self.all_results))
            
            # 获取当前页要显示的数据
            page_results = self.all_results[start_idx:end_idx]
            
            # 更新表格
            self.results_table.setRowCount(len(page_results))
            
            for i, result in enumerate(page_results):
                # 使用原始索引映射获取实际的帧序号，确保索引有效
                frame_index = result.get('frame_index', 0)
                
                # 检查索引是否有效，防止索引越界
                if frame_index < 0 or frame_index >= len(results.get('original_indices', [])):
                    self.logger.error(f"无效的帧索引: {frame_index}, 可用索引数量: {len(results.get('original_indices', []))}")
                    original_index = i  # 使用表格行索引作为后备值
                else:
                    try:
                        original_index = results['original_indices'][frame_index]
                    except (IndexError, KeyError) as e:
                        self.logger.error(f"获取原始索引时出错: {str(e)}")
                        original_index = i  # 使用表格行索引作为后备值
                
                # 显示帧序号（原始索引）
                self.results_table.setItem(i, 0, QTableWidgetItem(str(original_index)))
                
                # 获取并显示虚拟信道帧计数（十六进制）
                try:
                    # 尝试从结果中获取帧数据
                    frame = self.frames[original_index] if original_index < len(self.frames) else None
                    if frame:
                        # 使用通用的虚拟信道帧计数提取方法
                        from frame_processor import FrameProcessor
                        vc_frame_count = FrameProcessor.extract_virtual_channel_frame_count(frame)
                        if vc_frame_count > 0:
                            # 格式化为3字节（6位）十六进制，每两位用空格分隔
                            hex_str = format(vc_frame_count, '06X')
                            frame_count_hex = ' '.join(hex_str[i:i+2] for i in range(0, len(hex_str), 2))
                        else:
                            # 如果提取失败，回退到普通帧计数
                            frame_count = frame.get('frame_count', 0)
                            frame_count_hex = format_hex_with_space(frame_count)
                    else:
                        frame_count_hex = "N/A"
                except Exception as e:
                    self.logger.error(f"获取虚拟信道帧计数时出错: {str(e)}")
                    frame_count_hex = "错误"
                
                self.results_table.setItem(i, 1, QTableWidgetItem(frame_count_hex))
                
                # 显示虚拟信道
                vc = result.get('virtual_channel', 'N/A')
                self.results_table.setItem(i, 2, QTableWidgetItem(f"VC{vc}" if isinstance(vc, int) else str(vc)))
                
                # 字节错误率
                self.results_table.setItem(i, 3, QTableWidgetItem(f"{result['error_rate']:.6f}"))
                
                # 比特错误率
                bit_error_rate = result.get('bit_error_rate', 0)
                self.results_table.setItem(i, 4, QTableWidgetItem(f"{bit_error_rate:.8f}"))
                
                # 错误字节数
                self.results_table.setItem(i, 5, QTableWidgetItem(str(result.get('error_bytes', 0))))
                
                # 错误比特数
                self.results_table.setItem(i, 6, QTableWidgetItem(str(result.get('error_bits', 0))))
                
                # 总字节数
                self.results_table.setItem(i, 7, QTableWidgetItem(str(result.get('total_bytes', 0))))

                # 格式化误码位置 - 优化显示方式
                error_positions = result.get('error_positions', [])
                if error_positions:
                    # 创建更清晰的误码位置显示
                    positions_count = len(error_positions)
                    if positions_count <= 5:
                        # 少于等于5个位置，直接显示所有位置
                        positions_text = ", ".join(str(pos) for pos in sorted(error_positions))
                    elif positions_count <= 20:
                        # 6-20个位置，显示前5个和后面的数量
                        first_positions = sorted(error_positions)[:5]
                        positions_text = ", ".join(str(pos) for pos in first_positions) + f" 等{positions_count}个位置"
                    else:
                        # 超过20个位置，显示范围和总数
                        sorted_positions = sorted(error_positions)
                        min_pos = sorted_positions[0]
                        max_pos = sorted_positions[-1]
                        positions_text = f"{min_pos}~{max_pos} (共{positions_count}个)"
                    
                    # 添加双击提示
                    positions_text += " [双击查看详情]"
                else:
                    positions_text = "无误码"

                # 创建表格项并设置工具提示
                position_item = QTableWidgetItem(positions_text)
                if error_positions:
                    # 设置工具提示显示更多信息
                    tooltip_text = f"误码位置总数: {len(error_positions)}\n"
                    if len(error_positions) <= 10:
                        tooltip_text += "位置: " + ", ".join(str(pos) for pos in sorted(error_positions))
                    else:
                        first_10 = sorted(error_positions)[:10]
                        tooltip_text += "前10个位置: " + ", ".join(str(pos) for pos in first_10) + "..."
                    tooltip_text += "\n\n双击此单元格查看完整详情"
                    position_item.setToolTip(tooltip_text)
                
                self.results_table.setItem(i, 8, position_item)

                # 为高误码率的行添加红色背景
                if result['error_rate'] > 0.1:  # 10%以上误码率标红
                    for col in range(9):  # 更新为9列
                        item = self.results_table.item(i, col)
                        if item:
                            item.setBackground(Qt.red)
                elif result['error_rate'] > 0.05:  # 5-10%误码率标黄
                    for col in range(9):  # 更新为9列
                        item = self.results_table.item(i, col)
                        if item:
                            item.setBackground(Qt.yellow)

            # 调整表格列宽，但限制最大宽度，避免过宽表格导致性能问题
            self.results_table.resizeColumnsToContents()
            
            # 限制误码位置列的最大宽度
            if self.results_table.columnWidth(8) > 300:  # 更新为第8列
                self.results_table.setColumnWidth(8, 300)
                
            # 确保UI刷新
            QApplication.processEvents()
            
        except Exception as e:
            self.logger.error(f"加载页面数据失败: {str(e)}", exc_info=True)
            QMessageBox.critical(self, "错误", f"加载页面数据失败: {str(e)}")
            
    def _on_page_size_changed(self, text):
        """处理每页显示数量变化"""
        try:
            self.page_size = int(text)
            if len(self.all_results) > 0:
                # 重新计算总页数
                self.total_pages = (len(self.all_results) + self.page_size - 1) // self.page_size
                
                # 调整当前页，确保不超过总页数
                if self.current_page > self.total_pages:
                    self.current_page = self.total_pages
                
                # 更新显示
                self._update_pagination_controls()
                results = {'original_indices': [i for i in range(len(self.frames))]}
                self._load_current_page_data(results)
        except Exception as e:
            self.logger.error(f"更新每页显示数量时出错: {str(e)}")

    def _on_prev_page(self):
        """处理上一页按钮点击"""
        if self.current_page > 1:
            self.current_page -= 1
            results = {'original_indices': [i for i in range(len(self.frames))]}
            self._update_pagination_controls()
            self._load_current_page_data(results)

    def _on_next_page(self):
        """处理下一页按钮点击"""
        if self.current_page < self.total_pages:
            self.current_page += 1
            results = {'original_indices': [i for i in range(len(self.frames))]}
            self._update_pagination_controls()
            self._load_current_page_data(results)

    def _on_goto_page(self):
        """处理跳转到指定页按钮点击"""
        page = self.goto_page_input.text()
        if page.isdigit():
            page_num = int(page)
            if 1 <= page_num <= self.total_pages:
                self.current_page = page_num
                results = {'original_indices': [i for i in range(len(self.frames))]}
                self._update_pagination_controls()
                self._load_current_page_data(results)
                # 清空输入框
                self.goto_page_input.clear()

    def _on_cell_double_clicked(self, row, column):
        """处理表格单元格双击事件"""
        # 只有点击误码位置列（第8列）时才显示详情
        if column == 8:
            self._show_error_position_details(row)
        
    def _show_error_position_details(self, row):
        """显示误码位置详细信息"""
        try:
            # 计算在所有结果中的实际索引
            actual_index = (self.current_page - 1) * self.page_size + row
            
            if actual_index >= len(self.all_results):
                QMessageBox.warning(self, "警告", "无法获取该行的详细信息")
                return
            
            result = self.all_results[actual_index]
            error_positions = result.get('error_positions', [])
            
            if not error_positions:
                QMessageBox.information(self, "信息", "该帧没有误码位置")
                return
            
            # 获取帧索引
            frame_index = result.get('frame_index', 0)
            
            # 获取当前帧数据
            current_frame = None
            if (self.current_analysis_results and 
                'original_indices' in self.current_analysis_results and
                frame_index < len(self.current_analysis_results['original_indices'])):
                
                original_index = self.current_analysis_results['original_indices'][frame_index]
                if original_index < len(self.frames):
                    current_frame = self.frames[original_index]
            
            # 获取比较范围
            compare_ranges = None
            reference_frame = None
            if self.current_analysis_results:
                compare_ranges = self.current_analysis_results.get('compare_ranges')
                reference_frame = self.current_analysis_results.get('reference_frame')
            
            # 显示详细对话框
            dialog = ErrorPositionDialog(
                parent=self,
                frame_index=frame_index,
                error_positions=error_positions,
                compare_ranges=compare_ranges,
                reference_frame=reference_frame,
                current_frame=current_frame
            )
            dialog.exec_()
            
        except Exception as e:
            self.logger.error(f"显示误码位置详情时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"显示误码位置详情时出错: {str(e)}")

    def _on_frame_format_changed(self, format_text):
        """处理帧格式变化事件"""
        try:
            # 获取格式代码
            format_code = format_text.split('字节')[0]
            
            # 根据格式更新比对选项
            if format_code == "1092":
                # 1092字节格式：帧同步头在64-67，数据域在82-959
                self.mode_data_only.setText("数据域(878字节,范围82-959)")
                self.mode_header_data.setText("帧同步头+数据域(同步头:64-67字节,数据域:82-959字节)")
                self.mode_header_data.setEnabled(True)
                # 更新自定义范围提示
                self.custom_bytes_input.setPlaceholderText("例如: 64-67,82-959 (范围0-1091)")
                old_label = self.custom_bytes_widget.layout().itemAt(0).widget()
                old_label.setText("指定字节范围（0-1091）：")
                
            elif format_code == "1024":
                # 1024字节格式：帧同步头在0-3，数据域在18-895
                self.mode_data_only.setText("数据域(878字节,范围18-895)")
                self.mode_header_data.setText("帧同步头+数据域(同步头:0-3字节,数据域:18-895字节)")
                self.mode_header_data.setEnabled(True)
                # 更新自定义范围提示
                self.custom_bytes_input.setPlaceholderText("例如: 0-3,18-895 (范围0-1023)")
                old_label = self.custom_bytes_widget.layout().itemAt(0).widget()
                old_label.setText("指定字节范围（0-1023）：")
                
            elif format_code == "896":
                # 896字节格式：与1024字节格式相同，只是没有RS校验码
                self.mode_data_only.setText("数据域(878字节,范围18-895)")
                self.mode_header_data.setText("帧同步头+数据域(同步头:0-3字节,数据域:18-895字节)")
                self.mode_header_data.setEnabled(True)
                # 更新自定义范围提示
                self.custom_bytes_input.setPlaceholderText("例如: 0-3,18-895 (范围0-895)")
                old_label = self.custom_bytes_widget.layout().itemAt(0).widget()
                old_label.setText("指定字节范围（0-895）：")
            
            self.logger.info(f"帧格式已切换到: {format_code}字节")
            
        except Exception as e:
            self.logger.error(f"处理帧格式变化时出错: {str(e)}")

    def _get_frame_format(self):
        """获取当前选择的帧格式"""
        format_text = self.frame_format_combo.currentText()
        return format_text.split('字节')[0]